package 多线程;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//lock和condition机制实现生产者和消费者
//通过在Lock对象上调用newCondition()方法，将条件变量和一个锁对象进行绑定，进而控制并发程序访问竞争资源的安全。
public class ProAndCon2 {
    public static final int MAX_SIZE = 2;
    public static LinkedList<Integer> list = new LinkedList<>();

    public static Lock lock = new ReentrantLock();

    public static Condition full = lock.newCondition();

    public static Condition empty = lock.newCondition();

    class Producer implements Runnable{

        @Override
        public void run() {
            lock.lock();
            while(list.size()==MAX_SIZE){
                System.out.println("仓库已满，生产者"+Thread.currentThread().getName()+"不可生产");
                try {
                    full.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            list.add(1);
            System.out.println("生产者"+Thread.currentThread().getName()+"生产，仓库容量为"+list.size());
            full.signal();
            empty.signal();
            lock.unlock();
        }
    }

    class Consumer implements Runnable{

        @Override
        public void run() {
            lock.lock();
            while(list.size()==0){
                System.out.println("仓库为空，消费者"+Thread.currentThread().getName()+"不可消费");
                try {
                    empty.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            list.removeFirst();
            System.out.println("消费者"+Thread.currentThread().getName()+"消费,仓库容量为"+list.size());
            full.signal();
            empty.signal();
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ProAndCon2 proAndCon2 = new ProAndCon2();
        Producer producer = proAndCon2.new Producer();
        Consumer consumer = proAndCon2.new Consumer();
        for (int i = 0; i < 10; i++) {
            Thread pro = new Thread(producer);
            pro.start();
            Thread con = new Thread(consumer);
            con.start();
        }
    }

}
